package com.aoip.telemetry.telemetry.quartz.task.gpabno;

import com.aoip.telemetry.telemetry.core.redis.RedisCache;
import com.aoip.telemetry.telemetry.entity.enums.AbnoTypeEnum;
import com.aoip.telemetry.telemetry.entity.enums.CacheKeyEnum;
import com.aoip.telemetry.telemetry.entity.equipment.StInfoConfigEntity;
import com.aoip.telemetry.telemetry.entity.exception.GpAbnoInfoEntity;
import com.aoip.telemetry.telemetry.quartz.task.gpabno.mapper.StGpAbnoInfoMapper;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 异常信息入库
 *
 * @author chenbai
 * @version 1.0
 * @date 2022/9/24 14:19
 */
@Component
public class StGpAbnoInfoTask {

    private static DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private static StGpAbnoInfoTask stGpAbnoInfoTask;

    @Resource
    private RedisCache redisCache;

    @Resource
    private StGpAbnoInfoMapper mapper;

    @PostConstruct
    public void init() {
        stGpAbnoInfoTask = this;
    }

    public void calculate() {
        missMsg();
        offLine();
        storageFailAndAnalysisFail();
        missHeartBeat();
    }

    /**
     * 缺失报文异常
     * 核对是否缺失报文，依据规则为，根据站点最后一次上报时间，加上上报频率，是否超过当前时间，若不超过，则数据异常，否则正常。
     *
     * @author chenbai
     * @date 2022/9/30
     **/
    public void missMsg() {
        Collection<String> keys = stGpAbnoInfoTask.redisCache.keys(CacheKeyEnum.ST_GP_ABNO_INFO + ":" + AbnoTypeEnum.LAST_DATA_RECEIVED + ":*");
        LocalDateTime now = LocalDateTime.now();
        List<GpAbnoInfoEntity> list = new ArrayList<>();
        for (String key : keys) {
            String stCode = key.split(":")[2];
            StInfoConfigEntity stInfo = stGpAbnoInfoTask.redisCache.getCacheObject(CacheKeyEnum.STATION + ":" + stCode);
            if (stInfo == null) {
                continue;
            }
            Integer submitFrequency = stInfo.getSubmitFrequency();
            if (submitFrequency == null || submitFrequency <= 0) {
                continue;
            }
            String time = stGpAbnoInfoTask.redisCache.getCacheObject(key);
            LocalDateTime receiveDateTime = LocalDateTime.parse(time, dtf);
            LocalDateTime dateTime = receiveDateTime.plusMinutes(submitFrequency);
            if (now.compareTo(dateTime) > 0) {
                GpAbnoInfoEntity gpAbnoInfoEntity = new GpAbnoInfoEntity();
                gpAbnoInfoEntity.setCode(stCode);
                gpAbnoInfoEntity.setAbnoType(AbnoTypeEnum.MISSING_MESSAGE.getCode());
                gpAbnoInfoEntity.setBeginTime(receiveDateTime);
                list.add(gpAbnoInfoEntity);
            }
        }
        stGpAbnoInfoTask.redisCache.deleteObject(keys);
        saveGpAbnoInfo(list);
    }

    /**
     * 设备离线异常
     *
     * @author chenbai
     * @date 2022/10/2
     **/
    public void offLine() {
        Collection<String> keys = stGpAbnoInfoTask.redisCache.keys(CacheKeyEnum.ST_GP_ABNO_INFO + ":" + AbnoTypeEnum.OFF_LINE + ":*");
        List<GpAbnoInfoEntity> list = new ArrayList<>();
        for (String key : keys) {
            String stCode = key.split(":")[2];
            StInfoConfigEntity stInfo = stGpAbnoInfoTask.redisCache.getCacheObject(CacheKeyEnum.STATION + ":" + stCode);
            if (stInfo == null) {
                continue;
            }
            if (!stInfo.getStCd().equals(stCode)) {
                continue;
            }
            String time = stGpAbnoInfoTask.redisCache.getCacheObject(key);
            LocalDateTime dateTime = LocalDateTime.parse(time, dtf);
            GpAbnoInfoEntity entity = new GpAbnoInfoEntity();
            entity.setCode(stCode);
            entity.setAbnoType(AbnoTypeEnum.OFF_LINE.getCode());
            entity.setBeginTime(dateTime);
            list.add(entity);
        }
        stGpAbnoInfoTask.redisCache.deleteObject(keys);
        saveGpAbnoInfo(list);
    }

    /**
     * 1、监测数据入库失败异常 2、报文解析异常
     *
     * @author chenbai
     * @date 2022/10/2
     **/
    public void storageFailAndAnalysisFail() {
        Collection<String> storageFailKeys = stGpAbnoInfoTask.redisCache.keys(CacheKeyEnum.ST_GP_ABNO_INFO + ":" + AbnoTypeEnum.STORAGE_FAIL + ":*");
        Collection<String> exceptionKeys = stGpAbnoInfoTask.redisCache.keys(CacheKeyEnum.ST_GP_ABNO_INFO + ":" + AbnoTypeEnum.MESSAGE_EXCEPTION + ":*");
        List<String> keys = new ArrayList<>();
        keys.addAll(storageFailKeys);
        keys.addAll(exceptionKeys);
        List<GpAbnoInfoEntity> list = new ArrayList<>();
        for (String key : keys) {
            String stCode = key.split(":")[2];
            List<GpAbnoInfoEntity> gpAbnoInfoList = stGpAbnoInfoTask.redisCache.getCacheList(key);
            StInfoConfigEntity stInfo = stGpAbnoInfoTask.redisCache.getCacheObject(CacheKeyEnum.STATION + ":" + stCode);
            if (stInfo == null) {
                continue;
            }
            if (!stInfo.getStCd().equals(stCode)) {
                continue;
            }
            list.addAll(gpAbnoInfoList);
        }
        stGpAbnoInfoTask.redisCache.deleteObject(keys);
        saveGpAbnoInfo(list);
    }

    /**
     * 缺失心跳包
     *
     * @author chenbai
     * @date 2022/10/4
     **/
    public void missHeartBeat() {
        Collection<String> keys = stGpAbnoInfoTask.redisCache.keys(CacheKeyEnum.ST_GP_ABNO_INFO + ":" + AbnoTypeEnum.LAST_HEARTBEAT + ":*");
        LocalDateTime now = LocalDateTime.now();
        List<GpAbnoInfoEntity> list = new ArrayList<>();
        for (String key : keys) {
            String stCode = key.split(":")[2];
            StInfoConfigEntity stInfo = stGpAbnoInfoTask.redisCache.getCacheObject(CacheKeyEnum.STATION + ":" + stCode);
            if (stInfo == null) {
                continue;
            }
            Integer heartBeat = stInfo.getHeartBeat();
            if (heartBeat == null || heartBeat <= 0) {
                continue;
            }
            String time = stGpAbnoInfoTask.redisCache.getCacheObject(key);
            LocalDateTime receiveDateTime = LocalDateTime.parse(time, dtf);
            LocalDateTime dateTime = receiveDateTime.plusSeconds(heartBeat);
            if (now.compareTo(dateTime) > 0) {
                GpAbnoInfoEntity entity = new GpAbnoInfoEntity();
                entity.setCode(stCode);
                entity.setAbnoType(AbnoTypeEnum.OFF_LINE.getCode());
                entity.setBeginTime(receiveDateTime);
                list.add(entity);
            }
        }
        stGpAbnoInfoTask.redisCache.deleteObject(keys);
        saveGpAbnoInfo(list);
    }

    private void saveGpAbnoInfo(List<GpAbnoInfoEntity> list) {
        if (list == null || list.size() <= 0) {
            return;
        }
        list.forEach(stGpAbnoInfoTask.mapper::insert);
    }

}
